/**
 * @file common.h
 * Contém as definições comuns a todos os módulos.
 */

#ifndef _COMMON_H_
#define _COMMON_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <math.h>

#define JVM_VERSION 1.2
#define METHODAREA methodarea
#define MAINCLASS  mainclass
#define FRAMESTACK framestack

/* / 8 bytes sem sinal */
typedef uint8_t u1;

/* / 16 bytes sem sinal */
typedef uint16_t u2;

/* / 32 bytes sem sinal */
typedef uint32_t u4;

/* / 64 bytes sem sinal */
typedef uint64_t u8;

/* / 8 bytes com sinal */
typedef int8_t s1;

/* / 16 bytes com sinal */
typedef int16_t s2;

/* / 32 bytes com sinal */
typedef int32_t s4;

/* / 64 bytes com sinal */
typedef uint64_t s8;

typedef struct {

	/* / tag para informar que tipo de struct tem na union */
	u1 tag;

	/* / union que guarda um tipo de dado que é indicado pela tag */
	union {

		/* / tag 0x01 */
		struct {
			u2 lenght;
			u1 *bytes;
		} Utf8;

		/* / tag 0x03 */
		struct {
			u4 bytes;
		} Integer;

		/* / tag 0x04 */
		struct {
			u4 bytes;
		} Float;

		/* / tag 0x05 */
		struct {
			u4 high_bytes;
			u4 low_bytes;
		} Long;

		/* / tag 0x06 */
		struct {
			u4 high_bytes;
			u4 low_bytes;
		} Double;

		/* / tag 0x07 */
		struct {
			u2 name_index;
		} Class;

		/* / tag 0x08 */
		struct {
			u2 string_index;
		} String;

		/* / tag 0x09 */
		struct {
			u2 class_index;
			u2 name_and_type_index;
		} Fieldref;

		/* / tag 0x0a */
		struct {
			u2 class_index;
			u2 name_and_type_index;
		} Methodref;

		/* / tag 0x0b */
		struct {
			u2 class_index;
			u2 name_and_type_index;
		} InterfaceMethodref;

		/* / tag 0x0c */
		struct {
			u2 name_index;
			u2 descriptor_index;
		} NameAndType;

	} info;

} cp_info;

typedef struct _except_info {
	u2 start_pc;
	u2 end_pc;
	u2 handler_pc;
	u2 catch_type;
} except_info;

typedef struct _attr {
	u2 attribute_name_index;
	u4 attribute_lenght;

	union {
		struct {
			u2 index;
		} ConstantValue;

		struct {
			u2 max_stack;
			u2 max_locals;
			u4 code_lenght;
			u1 *code;
			u2 exception_table_lenght;
			except_info *exception_table;
			u2 attributes_count;
			struct _attr *attributes;
		} Code;

		struct {
			u2 count;
			u2 *index_table;
		} Exceptions;

		struct {
			u2 sourcefile_index;
		} Sourcefile;

	} info;

} attribute_info;

typedef struct {
	u2 access_flags;
	u2 name_index;
	u2 descriptor_index;
	u2 attributes_count;
	attribute_info *attributes;
} field_info;

typedef struct {
	u2 access_flags;
	u2 name_index;
	u2 descriptor_index;
	u2 attributes_count;
	attribute_info *attributes;
} method_info;

typedef struct _class_field_node {
	u2 cp_ref;
	u4 value;
	struct _class_field_node *next;
} class_field_node;

typedef struct {
	u4 magic_number;
	u2 minor_version;
	u2 major_version;
	u2 constant_pool_count;
	cp_info *constant_pool;
	u2 access_flags;
	u2 this_class;
	u2 super_class;
	u2 interfaces_count;
	u2 *interfaces;
	u2 fields_count;
	field_info *fields;
	u2 methods_count;
	method_info *methods;
	u2 attributes_count;
	attribute_info *attributes;
	class_field_node *class_fields;

} class_file;

typedef struct {
	u4 pc;
	u4 *stack;
	u4 *base;
	u4 *array;
	cp_info *constant_pool;
	u4 method_index; /* indice para o metodo no array methods[] */
	u4 attr_code_index; /* indice para atributo code */
} method_frame;

typedef struct _frame_stack {
	method_frame *frame;
	struct _frame_stack *next;
} frame_stack;

typedef struct {
	frame_stack *top;
} stack;

typedef struct _list_node {
	u1 *class_name;
	class_file *class;
	struct _list_node *next;
} list_node;

typedef struct {
	list_node *first;
} class_list;

typedef union intfloat {
	u4 inteiro;
	s4 sinteiro;
	float flutuante;
} intfloat;

/* / Informa se estamos em modo verbose */
u4 VERBOSE;

/* / Informa se é para imprimir o passo-a-passo da JVM */
u4 PRINT;

#endif
